﻿using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using HengTong.Model.Db;
using HengTong.Model.Db.System;
using HengTong.Model.Extension;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Models;
using UUIDNext;
using WalkingTec.Mvvm.Core;

namespace HengTong.Model.Services;

public interface IWechatAuthService
{
    Result<string> GetWechatLoginUrl();
    Task<Result<WechatAuthService.WechatUserInfo>> ProcessCallback(string code, string state);

    Task<Result<SysWechatUser>> ProcessMiniProgramLogin(string code);

    Task<Result<SysWechatUser>> ProcessAppLogin(string code);
}

public class WechatAuthService : IWechatAuthService
{
    private readonly WTMContext _context;
    private readonly IMemoryCache _memoryCache;
    private readonly ILogger<WechatAuthService> _logger;
    private readonly string _wechatWebAppId;
    private readonly string _wechatWebSecret;
    private readonly string _wechatWebRedirectUri;
    private readonly string _wechatMpAppId;
    private readonly string _wechatMpAppSecret;
    private readonly string _wechatAppAppId;
    private readonly string _wechatAppSecret;
    private readonly string _wechatAppRedirectUri;

    public WechatAuthService(ILogger<WechatAuthService> logger, WTMContext context, IMemoryCache memoryCache)
    {
        _logger = logger;
        _context = context;
        _memoryCache = memoryCache;

        /*if (!context.ConfigInfo.AppSettings.TryGetValue("WechatAppId", out var appId))
        {
#if DEBUG
            appId = "wx48b3136164586775";
#else
            throw new Exception("未配置WechatAppId");
#endif
        }

        if (!context.ConfigInfo.AppSettings.TryGetValue("WechatAppSecret", out var appSecret))
        {
#if DEBUG
            appSecret = "9b14d61df8701bddd97a782afd7d90fe";
#else
            throw new Exception("未配置WechatAppSecret");
#endif
        }

        if (!context.ConfigInfo.AppSettings.TryGetValue("WechatRedirectUri", out var redirectUri))
        {
#if DEBUG
            redirectUri = "http://info.henanlianchuang.com/";
#else
            throw new Exception("未配置WechatRedirectUri");
#endif
        }

        _wechatWebAppId = appId;
        _wechatWebSecret = appSecret;
        _wechatWebRedirectUri = redirectUri;*/
        _wechatWebAppId = context.GetSiteConfig().WechatWebAppId;
        _wechatWebSecret = context.GetSiteConfig().WechatWebSecret;
        _wechatWebRedirectUri = context.GetSiteConfig().WechatWebRedirectUri;
        _wechatMpAppId = context.GetSiteConfig().WechatMpAppId;
        _wechatMpAppSecret = context.GetSiteConfig().WechatMpAppSecret;
        _wechatAppAppId = context.GetSiteConfig().WechatAppAppId;
        _wechatAppSecret = context.GetSiteConfig().WechatAppSecret;
        _wechatAppRedirectUri = context.GetSiteConfig().WechatAppRedirectUri;
                                                                                                                                                                                                                                                
        
        if (string.IsNullOrWhiteSpace(_wechatWebAppId) || string.IsNullOrWhiteSpace(_wechatWebSecret) ||
            string.IsNullOrWhiteSpace(_wechatWebRedirectUri) || string.IsNullOrWhiteSpace(_wechatMpAppId) ||
            string.IsNullOrWhiteSpace(_wechatMpAppSecret) || string.IsNullOrWhiteSpace(_wechatAppAppId) ||
            string.IsNullOrWhiteSpace(_wechatAppSecret) || string.IsNullOrWhiteSpace(_wechatAppRedirectUri)
            )
        {
            throw new Exception("微信登录配置不完整，请检查 SysSiteConfig 中的相关设置");
        }
    }

    /// <summary>
    /// 获取微信登录链接
    /// </summary>
    /// <returns>微信登录链接</returns>
    public Result<string> GetWechatLoginUrl()
    {
        try
        {
            // 生成随机state参数防止CSRF攻击
            var state = Uuid.NewDatabaseFriendly(Database.SqlServer).ToString("N");
            // 将state存入缓存，有效期10分钟
            _memoryCache.Set($"{nameof(GetWechatLoginUrl)}_{state.ToLower()}", state, TimeSpan.FromMinutes(10));

            // 构建微信登录URL
            var redirectUri = Uri.EscapeDataString(_wechatWebRedirectUri);
            var scope = "snsapi_login";
            var url =
                $"https://open.weixin.qq.com/connect/qrconnect?appid={_wechatWebAppId}&redirect_uri={redirectUri}&response_type=code&scope={scope}&state={state}#wechat_redirect";

            _logger.LogInformation($"生成微信登录链接: {url}");

            return new Result<string>
            {
                Code = 200,
                Message = "获取微信登录链接成功",
                Data = url
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取微信登录链接失败");
            return new Result<string>("获取微信登录链接失败");
        }
    }

    /// <summary>
    /// 处理微信授权回调
    /// </summary>
    /// <param name="code">微信授权code</param>
    /// <param name="state">状态参数</param>
    /// <returns>微信用户信息</returns>
    public async Task<Result<WechatUserInfo>> ProcessCallback(string code, string state)
    {
        try
        {
            // 验证state参数，防止CSRF攻击
            var cachedState = _memoryCache.Get<string>($"{nameof(GetWechatLoginUrl)}_{state.ToLower()}");
            if (string.IsNullOrWhiteSpace(cachedState))
            {
                return new Result<WechatUserInfo>("无效的请求，state参数验证失败");
            }

            // 移除缓存中的state
            _memoryCache.Remove($"WechatLoginState_{state}");

            // 使用code获取access_token
            var client = new HttpClient();
            var tokenUrl =
                $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={_wechatWebAppId}&secret={_wechatWebSecret}&code={code}&grant_type=authorization_code";
            var response = await client.GetAsync(tokenUrl);

            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError($"获取微信access_token失败: {response.StatusCode}");
                return new Result<WechatUserInfo>("获取微信授权信息失败");
            }

            var tokenResponse = await JsonSerializer.DeserializeAsync<WechatTokenResponse>(
                await response.Content.ReadAsStreamAsync());

            if (tokenResponse?.ErrCode != 0)
            {
                _logger.LogError($"获取微信access_token失败: {tokenResponse?.ErrMsg}");
                return new Result<WechatUserInfo>($"获取微信授权信息失败: {tokenResponse?.ErrMsg}");
            }

            // 使用access_token获取用户信息
            var userInfoUrl =
                $"https://api.weixin.qq.com/sns/userinfo?access_token={tokenResponse.AccessToken}&openid={tokenResponse.OpenId}&lang=zh_CN";
            var userInfoResponse = await client.GetAsync(userInfoUrl);

            if (!userInfoResponse.IsSuccessStatusCode)
            {
                _logger.LogError($"获取微信用户信息失败: {userInfoResponse.StatusCode}");
                return new Result<WechatUserInfo>("获取微信用户信息失败");
            }

            var userInfo = await JsonSerializer.DeserializeAsync<WechatUserInfo>(
                await userInfoResponse.Content.ReadAsStreamAsync());

            return new Result<WechatUserInfo>
            {
                Code = 200,
                Message = "获取微信用户信息成功",
                Data = userInfo
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理微信回调失败");
            return new Result<WechatUserInfo>("处理微信授权回调失败");
        }
    }


    /// <summary>
    /// 处理微信小程序登录
    /// </summary>
    /// <param name="code">小程序登录code</param>
    /// <returns>微信用户信息</returns>
    public async Task<Result<SysWechatUser>> ProcessMiniProgramLogin(string code)
    {
        try
        {
            // 使用code获取小程序openid和session_key
            var client = new HttpClient();
            var url =
                $"https://api.weixin.qq.com/sns/jscode2session?appid={_wechatMpAppId}&secret={_wechatMpAppSecret}&js_code={code}&grant_type=authorization_code";

            var response = await client.GetAsync(url);
            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError($"获取微信小程序登录信息失败: {response.StatusCode}");
                return new Result<SysWechatUser>("获取微信小程序授权信息失败");
            }

            var wxResponse = await JsonSerializer.DeserializeAsync<WechatMiniProgramResponse>(
                await response.Content.ReadAsStreamAsync());

            if (wxResponse?.ErrCode != 0)
            {
                _logger.LogError($"微信小程序登录失败: {wxResponse?.ErrMsg}");
                return new Result<SysWechatUser>($"微信小程序授权失败: {wxResponse?.ErrMsg}");
            }

            // 查询数据库中是否存在该微信用户
            using var scope = _context.ServiceProvider.CreateScope();
            var dc = scope.ServiceProvider.GetRequiredService<WTMContext>().DC;

            var wechatUser = await dc.Set<SysWechatUser>()
                .AsNoTracking()
                .FirstOrDefaultAsync(x => x.MiniProgramOpenId == wxResponse.OpenId ||
                                          (!string.IsNullOrEmpty(wxResponse.UnionId) &&
                                           x.UnionId == wxResponse.UnionId));

            // 如果用户不存在，则创建新用户
            if (wechatUser == null)
            {
                wechatUser = new SysWechatUser
                {
                    MiniProgramOpenId = wxResponse.OpenId,
                    UnionId = wxResponse.UnionId,
                    CreateTime = DateTime.Now
                    // 小程序登录时，可能没有昵称和头像等信息
                };

                dc.Set<SysWechatUser>().Add(wechatUser);
                await dc.SaveChangesAsync();

                // 重新查询获取完整的用户对象（包含ID）
                wechatUser = await dc.Set<SysWechatUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(x => x.MiniProgramOpenId == wxResponse.OpenId);
            }
            else
            {
                // 如果已存在更新数据
                await dc.Set<SysWechatUser>().Where(w => w.ID == wechatUser.ID).ExecuteUpdateAsync(u => u
                    .SetProperty(p => p.MiniProgramOpenId,
                        string.IsNullOrEmpty(wxResponse.OpenId) ? wechatUser.MiniProgramOpenId : wxResponse.OpenId)
                    .SetProperty(p => p.UnionId,
                        string.IsNullOrEmpty(wxResponse.UnionId) ? wechatUser.UnionId : wxResponse.UnionId));
                await dc.SaveChangesAsync();
            }

            return new Result<SysWechatUser>
            {
                Code = 200,
                Message = "微信小程序登录成功",
                Data = wechatUser
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理微信小程序登录失败");
            return new Result<SysWechatUser>("处理微信小程序登录失败");
        }
    }

    /// <summary>
    /// 微信App端登录处理
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public async Task<Result<SysWechatUser>> ProcessAppLogin(string code)
    {
        try
        {
            // 使用code获取App端openid和unionid
            var client = new HttpClient();
            var url =
                $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={_wechatAppAppId}&secret={_wechatAppSecret}&code={code}&grant_type=authorization_code";

            var response = await client.GetAsync(url);
            if (!response.IsSuccessStatusCode)
            {
                _logger.LogError($"获取App端登录信息失败: {response.StatusCode}");
                return new Result<SysWechatUser>("获取App授权信息失败");
            }

            var wxResponse = await JsonSerializer.DeserializeAsync<WechatTokenResponse>(
                await response.Content.ReadAsStreamAsync());

            if (wxResponse?.ErrCode != 0)
            {
                _logger.LogError($"App登录失败: {wxResponse?.ErrMsg}");
                return new Result<SysWechatUser>($"App授权失败: {wxResponse?.ErrMsg}");
            }

            // 查询数据库中是否存在该用户
            using var scope = _context.ServiceProvider.CreateScope();
            var dc = scope.ServiceProvider.GetRequiredService<WTMContext>().DC;

            var wechatUser = await dc.Set<SysWechatUser>()
                .AsNoTracking()
                .FirstOrDefaultAsync(x => x.WebOpenId == wxResponse.OpenId ||
                                          (!string.IsNullOrEmpty(wxResponse.UnionId) &&
                                           x.UnionId == wxResponse.UnionId));

            // 如果用户不存在，则创建新用户
            if (wechatUser == null)
            {
                wechatUser = new SysWechatUser
                {
                    WebOpenId = wxResponse.OpenId,
                    UnionId = wxResponse.UnionId,
                    CreateTime = DateTime.Now
                    // 其他信息可以后续补充
                };

                dc.Set<SysWechatUser>().Add(wechatUser);
                await dc.SaveChangesAsync();

                // 重新查询获取完整的用户对象（包含ID）
                wechatUser = await dc.Set<SysWechatUser>()
                    .AsNoTracking()
                    .FirstOrDefaultAsync(x => x.WebOpenId == wxResponse.OpenId);
            }
            else
            {
                // 如果已存在更新数据
                await dc.Set<SysWechatUser>().Where(w => w.ID == wechatUser.ID).ExecuteUpdateAsync(u => u
                    .SetProperty(p => p.WebOpenId,
                        string.IsNullOrEmpty(wxResponse.OpenId) ? wechatUser.WebOpenId : wxResponse.OpenId)
                    .SetProperty(p => p.UnionId,
                        string.IsNullOrEmpty(wxResponse.UnionId) ? wechatUser.UnionId : wxResponse.UnionId));
                await dc.SaveChangesAsync();
            }

            return new Result<SysWechatUser>
            {
                Code = 200,
                Message = "App登录成功",
                Data = wechatUser
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "处理App登录失败");
            return new Result<SysWechatUser>("处理App登录失败");
        }
    }


// 微信token响应模型
    public class WechatTokenResponse
    {
        [JsonPropertyName("access_token")] public string AccessToken { get; set; }

        [JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }

        [JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }

        [JsonPropertyName("openid")] public string OpenId { get; set; }
        [JsonPropertyName("unionid")] public string UnionId { get; set; }

        [JsonPropertyName("scope")] public string Scope { get; set; }

        [JsonPropertyName("errcode")] public int ErrCode { get; set; }

        [JsonPropertyName("errmsg")] public string ErrMsg { get; set; }
    }

// 微信用户信息模型
    public class WechatUserInfo
    {
        [JsonPropertyName("openid")] public string OpenId { get; set; }

        [JsonPropertyName("nickname")] public string Nickname { get; set; }

        [JsonPropertyName("sex")] public int Sex { get; set; }

        [JsonPropertyName("province")] public string Province { get; set; }

        [JsonPropertyName("city")] public string City { get; set; }

        [JsonPropertyName("country")] public string Country { get; set; }

        [JsonPropertyName("headimgurl")] public string HeadImgUrl { get; set; }

        [JsonPropertyName("privilege")] public string[] Privilege { get; set; }

        [JsonPropertyName("unionid")] public string UnionId { get; set; }
    }

// 小程序登录响应模型
    public class WechatMiniProgramResponse
    {
        [JsonPropertyName("openid")] public string OpenId { get; set; }

        [JsonPropertyName("session_key")] public string SessionKey { get; set; }

        [JsonPropertyName("unionid")] public string UnionId { get; set; }

        [JsonPropertyName("errcode")] public int ErrCode { get; set; }

        [JsonPropertyName("errmsg")] public string ErrMsg { get; set; }
    }
}